"""
__new__ 和 __init__ 的基本原则
1、__init__ 不能有返回值
2、__new__ 返回一个新的属于该类的实例，当前类__init__ 才会被调用
3、如果 __new__ 不返回值，不创建对象，__init__ 也不会被调用
"""


class A:
    def __new__(cls):
        print("A.new")
        return super(A, cls).__new__(cls)  # 返回了一个本类的新对象，然后会调用本类的 __init__

    def __init__(self):
        print("A.init")


class B(A):
    def __new__(cls):
        print("B.new")  # 没有返回值，不创新新对象，也不调用 __init__

    def __init__(self):
        super().__init__()
        print("B.init")


class C:
    def __new__(cls):
        print("C.new")
        return super(C, cls).__new__(cls)

    def __init__(self):
        print("C.init")


class D(A):
    def __new__(cls):
        print("D.new")
        # d super:<super: <class 'D'>, <D object>>
        print(f'd super:{super(D,cls)}')
        ins = super(D, cls).__new__(cls)
        # <__main__.D object at 0x10a300310>，返回时一个 D 的实例
        print(f'instance:{ins}')
        return ins

    def __init__(self):
        super().__init__()
        print("D.init")


print("="*30)
b = B()  # B.new，__new__ 没有返回值，什么都不做
print("="*30)
c = C()  # 新建了 C 的新实例，继续调用当前类的 __init__
# C.new
# C.init
print("="*30)
# [<class '__main__.D'>, <class '__main__.A'>, <class 'object'>]
print(D.mro())
d = D()
"""
    __new__ 调用了 D 的super，按照上面 mro ,寻找 D 之后的 __new__，
    也就是 A 的 __new__，这时候打印 A.new
    之后继续调用 A 之后的 __new__，A 之后是 object，也就是调用object.__new__
    新建了一个 A 对象实例返回。然后执行 A 的 __init__,
    打印 A.init。A 构造和初始化完成，返回到 D 的 __new__
    返回 D 的实例，然后继续执行 D 的 __init__，打印 D.init
    所以打印结果就是: D.new A.new A.init D.init
"""
print("="*30)
